home *** CD-ROM | disk | FTP | other *** search
- # classdoc.awk
- #
- # This awk script tries to produce a manual page from a C++ header file.
- # The idea is to make the documentation more readable, without maintaining
- # a separate file. Typical usage:
- #
- # gawk -f classdoc.awk list.H | nroff -man
- #
- # Although the result may not be exactly as intended, nothing in the file
- # (except #if, #ifdef, #ifndef, #endif) is supposed to be thrown away.
- # Major problem: comments associated with stuff that is saved (typedef, #define,
- # etc.), is not saved but appears with some unrelated code.
- # Improvemnts are gratefully accepted.
- #
- # Author: Dag Michael Bruck, Department of Automatic Control, Lund Institute
- # of Technology, Box 118, S-221 00 Lund, SWEDEN. E-mail: dag@control.lth.se
- #
- # Version: 2.5 Last change: 1990-05-15
- #
- FNR == 1 {
- "ls -l " FILENAME | getline Date;
- Date = substr(Date, 33, 12);
- print ".TH",FILENAME,"C++","\""Date"\"","\"ClassDoc 2.5\"","\\&";
- Section = "None";
- SubSect = "None";
- ContinueStat = 0;
- }
- #
- # Stop class ducumentation
- #
- /CLASSDOC[ \t]+OFF/ {
- while ($0 !~ /CLASSDOC[ \t]+ON/)
- getline;
- getline;
- }
- #
- # #define macro, placed at end of manual page
- #
- $1 == "#define" {
- $0 = dropfirst($0);
- match($0, /[A-Za-z0-9_]+(\([^\)]*\))?/);
- save("define", substr($0, RSTART, RLENGTH));
- eatcontinuation();
- next;
- }
- #
- # #include files, placed at end
- #
- $1 == "#include" {
- save("include", substr($2, 2, length($2)-2));
- next;
- }
- #
- # Drop some cpp directives
- #
- $1 == "#if" { next; }
- $1 == "#ifdef" { next; }
- $1 == "#ifndef" { next; }
- $1 == "#else" { next; }
- $1 == "#elif" { next; }
- $1 == "#endif" { next; }
- #
- # Extrnal declarations, placed at end
- #
- $1 == "extern" {
- save("extern", dropfirst($0));
- next;
- }
- #
- # Typedef declaration, placed at end
- #
- $1 == "typedef" {
- save("typedef", dropfirst($0));
- next;
- }
- #
- # Class declarations, place at end
- #
- $1 ~ /^class$|^struct$/ && $2 ~ /;$/ {
- save("classdecl", $1 " " substr($2, 1, length($2)-1));
- next;
- }
- #
- # C++ comment (the /* ... */ variant is not recognized)
- #
- $1 ~ /^\/\// {
- if (!(Section ~ /Description|Class|Code/))
- section("Description", "DESCRIPTION");
- if (InComment == 0) {
- if (Section == "Description")
- print ".fi\n.ft R\n.PP";
- else
- print ".fi\n.ft R\n.sp 0.1v\n.RS 0.25i";
- };
- if (NF == 1)
- print ".PP";
- else {
- match($0, /\/\/[ ]*/);
- print substr($0, RSTART+RLENGTH);
- }
- InComment = 1;
- next;
- }
- #
- # Class definition
- #
- $1 ~ /^class$/ && Section != "Class" {
- section("Class", "CLASS " $2);
- if (NF > 4) {
- subsect("Base", "Base class");
- print ".fi\n.ft R";
- for (i=4; i < NF; i++)
- print $i;
- print ".nf\n.ft B";
- };
- next;
- }
- #
- # Struct definition - almost a class
- #
- $1 ~ /^struct$/ && Section != "Class" {
- section("Class", "STRUCT " $2);
- subsect("Public", "Public members");
- next;
- }
- #
- # End of class definition
- #
- $1 == "};" {
- Section = "None";
- SubSect = "None";
- InComment = 0;
- next;
- }
- #
- # Friend declaration, only in classes
- #
- $1 == "friend" {
- subsect("Friend", "Friends");
- print dropfirst($0);
- next;
- }
- #
- # Public, protected and private parts of a class
- #
- /public:/ {
- subsect("Public", "Public members");
- next;
- }
- /protected:/ {
- subsect("Protected", "Protected members");
- next;
- }
- /private:/ {
- subsect("Private", "Private members");
- next;
- }
- #
- # Everything else inside a class (not comments)
- #
- Section == "Class" {
- if (InComment == 1)
- print ".RE\n.PP\n.nf\n.ft B";
- if (NF > 0) print substr($0, index($0, $1));
- if (match($0, /,[ \t]*$/)) {
- if (ContinueStat == 0) print ".RS 1i\n.ft B";
- ContinueStat = 1;
- }
- else if (ContinueStat == 1) {
- print ".RE\n.ft B";
- ContinueStat = 0;
- }
- InComment = 0;
- next;
- }
- #
- # Blank lines
- #
- NF == 0 {
- print ".PP"
- if (Section == "Code")
- print ".nf\n.ft B";
- next;
- }
- #
- # Everything else (outside classes)
- #
- {
- if (Section != "Code")
- section("Code", "CODE");
- if (InComment == 1) {
- print ".RE\n.PP\n.nf\n.ft B";
- InComment = 0;
- };
- print;
- next;
- }
- #
- # Post-processing: list class declarations, external declarations,
- # macro definitions and includec files.
- #
- END {
- if (issaved("classdecl")) {
- print ".SH CLASS DECLARATIONS\n.nf";
- printsaved("classdecl");
- }
- if (issaved("extern")) {
- print ".SH EXTERNAL DECLARATIONS\n.nf";
- printsaved("extern");
- }
- if (issaved("typedef")) {
- print ".SH TYPE DEFINITIONS\n.nf";
- printsaved("typedef");
- }
- if (issaved("define")) {
- print ".SH DEFINED MACROS\n.nf";
- printsaved("define");
- }
- if (issaved("include")) {
- print ".SH INCLUDED FILES\n.nf";
- printsaved("include");
- }
- }
- #
- # dropfirst(str) - returns string without its first field
- #
- function dropfirst(str)
- {
- if (match(str, /^[ \t]*[^ \t]*[ \t]+/))
- return substr(str, RLENGTH+1);
- else
- return str;
- }
- #
- # save, ... - functions for saving text in an area, printing it, etc.
- #
- function save(area, str)
- {
- TextCount[area]++;
- TextArea[area, TextCount[area]] = str;
- }
-
- function issaved(area)
- {
- return TextCount[area] > 0;
- }
-
- function printsaved(area, i)
- {
- for (i = 1; i <= TextCount[area]; i++)
- print TextArea[area, i];
- }
- #
- # section(sect, heading) - change section, no subsection
- #
- function section(sect, heading)
- {
- if (sect != Section) {
- Section = sect;
- print ".SH", heading;
- print ".nf\n.ft B";
- InComment = 0;
- }
- SubSect = "None";
- }
- #
- # subsect(subs, heading) - change subsection
- #
- function subsect(subs, heading)
- {
- if (subs != SubSect) {
- SubSect = subs;
- print ".SS", heading;
- print ".nf\n.ft B";
- InComment = 0;
- }
- }
- #
- # eatcontinuation() - eat continuation lines (preceding line ended in \)
- #
- function eatcontinuation()
- {
- while ($0 ~ /\\$/)
- getline;
- }
-